/********************************************************************************/
/* flashcode.c									*/ 
/* Written by: Kyle Castille							*/
/* Updated by: Michael Haag (6/27/01)						*/	                                               
/* This program will create a dummy data buffer with an incrementing count	*/
/* in internal memory, and then program this data to the AM29LV800-90 Flash	*/
/* which is a 1M x 8/512k x 16, 90 ns Flash memory.				*/
/* 										*/
/* This program assumes that the ARDY interface is used, so no software		*/
/* checking is done to detect end of operation for erase or program		*/
/*										*/
/********************************************************************************/
//#define CHIP_6201

#define		CE1_ADDRS	0x01400000
#define		INT_MEM		0x80000000
#define 	CE1_CNTRL	0x01800004

#define 	FLASH_ADDRS		CE1_ADDRS
#define 	SRC_ADDRS		INT_MEM
#define 	LENGTH			0x400
#define 	TRUE			1
#define 	FALSE			0

#include <csl.h>
#include <csl_emif.h>

void emif_config();
void load_source (short * source, int num_words);
void erase_flash(int * flash_addrs);
void program_flash(short * source, int * flash_addrs, int num_words);
/*
void
main(){
	int * flash_ptr = (int *)FLASH_ADDRS;
	short * src_ptr = (short *)SRC_ADDRS;

 	 CSL_init();

	emif_config();
	load_source(src_ptr, LENGTH);
	erase_flash(flash_ptr);
	program_flash(src_ptr, flash_ptr, LENGTH);
	printf("Successful erase and program!!!");
}
//*/
/****************************************************************************/
/* emif_config :Routine to configure the Emif for operation with 			*/
/*		AM29LV800-90 at CE1.  This routine sets the CE1 control register	*/
/*		for a 32 bit asynchronous memory interface with the following 		*/
/*		parameters:								*/
/*		Mtype = 010 (32-bit async memory)					*/
/*		Read Setup/Strobe/Hold = 1/21/3						*/
/*		Write Setup/Strobe/Hold = 2/13/3					*/
/*											*/
/****************************************************************************/

void emif_config(){
	/* Create Global Control Register field */
	Uint32 global_ctl = EMIF_GBLCTL_RMK(
				EMIF_GBLCTL_NOHOLD_DEFAULT,
				EMIF_GBLCTL_SDCEN_DISABLE,
				EMIF_GBLCTL_SSCEN_DISABLE,
				EMIF_GBLCTL_CLK1EN_ENABLE,
				EMIF_GBLCTL_CLK2EN_DISABLE,
				EMIF_GBLCTL_SSCRT_CPUOVR2,
				EMIF_GBLCTL_RBTR8_HPRI);
	
	/* Create CE1 Control Register field */
	Uint32 ce0_control = EMIF_CECTL_RMK(
				EMIF_CECTL_WRSETUP_OF(2),
				EMIF_CECTL_WRSTRB_OF(14),
				EMIF_CECTL_WRHLD_OF(3),
				EMIF_CECTL_RDSETUP_OF(1),
				EMIF_CECTL_RDSTRB_OF(21),
				EMIF_CECTL_MTYPE_ASYNC32,				
				EMIF_CECTL_RDHLD_OF(3) );
				
	EMIF_configArgs(
				EMIF_GBLCTL_OF(global_ctl),		/* global control 	 */
				EMIF_CECTL_OF(ce0_control),		/* 32-bit async mem	 */
				EMIF_CECTL_OF(0x00000018),      	/* CE1 control 		 */
				EMIF_CECTL_OF(0x00000018),		/* CE2 control		 */
				EMIF_CECTL_OF(0x00000018),		/* CE3 control		 */
				EMIF_SDCTL_OF(0x0388F000), 		/* SDRAM control 	 */
				EMIF_SDTIM_OF(0x00800040)		/* SDRAM timing		 */
		);
}

/****************************************************************************/
/* load_source : Routine to load the source memory with data.  This routine	*/
/*		loads an incrementing count into the source memory for  	*/
/*		demonstration purposes.					     	*/
/* Inputs:									*/
/*	source_ptr	: 	Address to be used as the source buffer		*/
/*	length   	: 	Length to be programmed				*/
/*										*/
/****************************************************************************/

void load_source(short * source_ptr, int length)
{
	int i;

	for (i = 0; i < length; i ++){
		* source_ptr++ = i;
	}
}

/****************************************************************************/
/* erase_flash : Routine to erase entire FLASH memory AM29LV800 (1M x 8bit/	*/
/*		512k x 16bit)							*/
/* Inputs:									*/
/*	flash_ptr: Address of the FLASH PEROM			           	*/
/* 										*/
/****************************************************************************/
	
void erase_flash(int * flash_ptr)
{
	/* Control addresses are left shifted so that 		*/
	/*  they appear correctly on the EMIF's EA[19:2]	*/
	/* Byte address << 2 == Word Address				*/

	int * ctrl_addr1 = (int *) ((int)flash_ptr + (0x555 << 2));
	int * ctrl_addr2 = (int *) ((int)flash_ptr + (0x2aa << 2));;

	* ctrl_addr1 = 0x00aa;	/* Erase sequence writes to addr1 and addr2 	*/
	* ctrl_addr2 = 0x0055;	/*  with this data 								*/
	* ctrl_addr1 = 0x0080;
	* ctrl_addr1 = 0x00aa;
	* ctrl_addr2 = 0x0055;
	* ctrl_addr1 = 0x0010;
}

/****************************************************************************/
/* program_flash: Routine to program FLASH AM29LV800				*/
/* Inputs:									*/
/*	flash_ptr	: Address of the FLASH  				*/
/*	source_ptr	: Address of the array containing the code to program 	*/
/* 	length		: Length to be programmed				*/
/*										*/
/****************************************************************************/

void program_flash(short * source_ptr, int * flash_ptr, int length)
{
	int i;

	/* Control addresses are left shifted so that 	 	*/
	/*  they appear correctly on the EMIF's EA[19:2]	*/
	/* Byte address << 2 == Word Address		    	*/
	int * ctrl_addr1 = (int *) ((int)flash_ptr + (0x555 << 2));
	int * ctrl_addr2 = (int *) ((int)flash_ptr + (0x2aa << 2));;
		
	for (i = 0; i < length; i++){

		* ctrl_addr1 = 0x00aa;
		* ctrl_addr2 = 0x0055;
		* ctrl_addr1 = 0x00a0;

		* flash_ptr++ = * source_ptr++;
	}
}

